package com.starview.star.compiler.cafe.compile;

import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.LocalVariableNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.TypeInsnNode;
import org.objectweb.asm.tree.VarInsnNode;

import com.starview.platform.data.type.IType;
import com.starview.platform.data.type.Location;
import com.starview.platform.data.type.TypeUtils;
import com.starview.star.code.repository.CodeCatalog;
import com.starview.star.compiler.ErrorReport;
import com.starview.star.compiler.util.AccessMode;

public class ArgDefiner implements Definer
{
  protected final MethodNode mtd;
  protected final HWM hwm;
  protected final LabelNode endLabel;
  protected final CodeCatalog bldCat;

  public ArgDefiner(MethodNode mtd, HWM hwm, LabelNode endLabel, CodeCatalog bldCat)
  {
    this.mtd = mtd;
    this.hwm = hwm;
    this.endLabel = endLabel;
    this.bldCat = bldCat;
  }

  @Override
  public VarInfo declareArg(Location loc, String name, int varOffset, IType varType, CafeDictionary dict,
      AccessMode access, boolean isInited, ErrorReport errors)
  {
    ISpec vrSpec = SrcSpec.generic(loc, varType, dict, bldCat, errors);

    VarInfo var = dict.declareLocal(name, vrSpec, isInited, access);
    if (isInited) {
      LabelNode startLabel = new LabelNode();
      mtd.localVariables.add(new LocalVariableNode(var.getJavaSafeName(), var.getJavaSig(), null, startLabel,
          endLabel, var.getOffset()));
      InsnList ins = mtd.instructions;
      ins.add(startLabel);
      if (!TypeUtils.isRawType(varType)) {
        hwm.probe(1);
        ins.add(new VarInsnNode(Opcodes.ALOAD, var.getOffset()));
        ins.add(new TypeInsnNode(Opcodes.CHECKCAST, var.getJavaType()));
        ins.add(new VarInsnNode(Opcodes.ASTORE, var.getOffset()));
      }
    }
    return var;
  }
}